// Copyright 2021 Guoyoko. All Rights Reserved.

#include "SWGameViewportClient.h"
#include "Engine/LocalPlayer.h"
#include "GameFramework/PlayerController.h"


USWGameViewportClient* GVC = nullptr;

USWGameViewportClient::USWGameViewportClient()
{
	GVC = this;
}

bool USWGameViewportClient::InputKey(const FInputKeyEventArgs& EventArgs)
{
	if (!PlayerController)
	{
		ULocalPlayer* const TargetPlayer = GEngine->GetLocalPlayerFromControllerId(this, EventArgs.ControllerId);
		PlayerController = TargetPlayer->PlayerController;
	}

	if (EventArgs.Key == EKeys::LeftMouseButton && EventArgs.Event == EInputEvent::IE_Pressed)
	{
		TArray<FHitResult> OutHits;
		if (LineTrace(OutHits))
		{
			if (OutHits.Num())
			{
				AActor* HitActor = OutHits[0].Actor.Get();
				if (HitActor->IsA(AActor::StaticClass() ))
				{
					DelegateOnSelectedActor.Broadcast(HitActor);
				}
				else DelegateOnSelectedActor.Broadcast(NULL);
			}
			else
			{
				DelegateOnSelectedActor.Broadcast(NULL);
			}
		}

	}

	if (DroppedObject && EventArgs.Event == IE_Released)
	{
		if (EventArgs.Key == EKeys::LeftMouseButton)
		{

			DroppedObject = nullptr;
		}
		else if (EventArgs.Key == EKeys::RightMouseButton)
		{
			GetWorld()->DestroyActor(Cast<AActor>(DroppedObject));
			DroppedObject = nullptr;
		}

	}

	return Super::InputKey(EventArgs);
}

void USWGameViewportClient::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

	UpdateDroppedObject();
}

void USWGameViewportClient::PlaceActor(AActor* _NewActor)
{

	int32 X = Viewport->GetSizeXY().X / 2;
	int32 Y = Viewport->GetSizeXY().Y * 2 / 3;
	Viewport->SetMouse(X, Y);

	SetDroppedObjects(_NewActor);
}

bool USWGameViewportClient::LineTrace(TArray<struct FHitResult>& OutHits, TArray<AActor*> IgnoredActors, float LineTraceLength)
{
	if (PlayerController)
	{
		IgnoredActors.Add(PlayerController->GetPawn());


		FVector MouseWorldLocation, MouseWorldDirction;
		PlayerController->DeprojectMousePositionToWorld(MouseWorldLocation, MouseWorldDirction);
		FVector Start = MouseWorldLocation;
		FVector End = MouseWorldLocation + MouseWorldDirction * LineTraceLength;

		FCollisionQueryParams Params = FCollisionQueryParams::DefaultQueryParam;
		Params.AddIgnoredActors(IgnoredActors);

		return Super::GetWorld()->LineTraceMultiByChannel(OutHits, Start, End, ECollisionChannel::ECC_WorldStatic, Params);
	}

	return false;
}

void USWGameViewportClient::SetDroppedObjects(UObject* _Objects)
{
	DroppedObject = _Objects;
}

void USWGameViewportClient::UpdateDroppedObject()
{
	if (DroppedObject)
	{
		TArray<FHitResult> OutHits;
		
		TArray<AActor*> IgnoredActors;
		IgnoredActors.Add(Cast<AActor>(DroppedObject));
		if (LineTrace(OutHits, IgnoredActors))
		{
			Cast<AActor>(DroppedObject)->SetActorLocation(OutHits[0].ImpactPoint);
		}
	}
}

